﻿' LibWowArmory
' by Ronald M. Clifford (roncli@roncli.com)
'
' This source code is released under the GNU Library General Public License (LGPL) Version 2.1.

Imports roncliProductions.LibWowArmory.Character.Achievements.Category
Imports System
Imports System.Collections.ObjectModel
Imports System.Globalization
Imports System.IO
Imports System.Linq
Imports System.Xml.Serialization
Imports System.Web

Namespace roncliProductions.LibWowArmory.Character.Achievements

    Public Class CharacterAchievements
        Inherits WowArmoryData

        Private caPage As New Schema.page
        Private aRecentAchievements As New Collection(Of Achievement)
        Private cCategories As New Collection(Of CategoryInfo)

        ''' <summary>
        ''' The realm the character is on
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Property Realm As String

        ''' <summary>
        ''' The name of the character
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Property Name As String

        ''' <summary>
        ''' The URL that will be used to retrieve the character's achievements from the Armory
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Overrides ReadOnly Property URL As String
            Get
                Return String.Format(CultureInfo.InvariantCulture, "http://www.wowarmory.com/character-achievements.xml?r={0}&n={1}", Realm, Name)
            End Get
        End Property

        ''' <summary>
        ''' Indicates to the inherited class that this request does not require login
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Overrides ReadOnly Property RequiresLogin As Boolean
            Get
                Return False
            End Get
        End Property

        ''' <summary>
        ''' The total number of achievement points earned by this character
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public ReadOnly Property AchievementPointsEarned As Integer
            Get
                Return caPage.achievements.First.summary.First.c.First.points
            End Get
        End Property

        ''' <summary>
        ''' The total possible number of achievement points available to earn in the game
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public ReadOnly Property AchievementPointsTotal As Integer
            Get
                Return caPage.achievements.First.summary.First.c.First.totalPoints
            End Get
        End Property

        ''' <summary>
        ''' The total number of achievements earned by this character
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public ReadOnly Property AchievementsEarned As Integer
            Get
                Return caPage.achievements.First.summary.First.c.First.earned
            End Get
        End Property

        ''' <summary>
        ''' The total possible number of achievements available to earn in the game
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public ReadOnly Property AchievementsTotal As Integer
            Get
                Return caPage.achievements.First.summary.First.c.First.total
            End Get
        End Property

        ''' <summary>
        ''' The most recent achievements earned by this character
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public ReadOnly Property RecentAchievements As Collection(Of Achievement)
            Get
                Return aRecentAchievements
            End Get
        End Property

        ''' <summary>
        ''' The achievement categories for this character
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public ReadOnly Property Categories As Collection(Of CategoryInfo)
            Get
                Return cCategories
            End Get
        End Property

        ''' <summary>
        ''' A constructor to load a character's achievements by realm and character name
        ''' </summary>
        ''' <param name="strRealm"></param>
        ''' <param name="strName"></param>
        ''' <remarks></remarks>
        Public Sub New(ByVal strRealm As String, ByVal strName As String)
            Realm = strRealm
            Name = strName
            Load()
        End Sub

        ''' <summary>
        ''' Loads the character's achievements from the armory
        ''' </summary>
        ''' <remarks></remarks>
        Public Sub Load()
            Dim strKey As String = String.Format(CultureInfo.InvariantCulture, "LibWowArmory.CharacterAchievements.{0}.{1}", Realm, Name)
            If Cache.Cache(strKey) Is Nothing Then
                MyBase.Retrieve()

                Dim xsSerializer As New XmlSerializer(caPage.GetType)

                Using srXML As New StringReader(MyBase.Data)
                    caPage = CType(xsSerializer.Deserialize(srXML), Schema.page)
                End Using

                Cache.Cache.Insert(strKey, caPage, Nothing, Date.UtcNow.AddDays(1), Nothing, Caching.CacheItemPriority.Normal, Nothing)
            Else
                caPage = CType(Cache.Cache(strKey), Schema.page)
            End If

            If caPage Is Nothing Then
                Throw New ArgumentException("The character you are trying to retrieve achievements for does not exist.")
            End If
            If caPage.characterInfo Is Nothing Then
                Throw New ArgumentException("The character you are trying to retrieve achievements for does not exist.")
            End If
            If caPage.characterInfo.First.character Is Nothing Then
                Throw New ArgumentException("The character you are trying to retrieve achievements for does not exist.")
            End If
            If caPage.achievements Is Nothing Then
                Throw New ArgumentException("The character you are trying to retrieve achievements for does not exist.")
            End If

            For Each aAchievement As Schema.achievement In caPage.achievements.First.summary.First.achievement
                aRecentAchievements.Add(New Achievement(aAchievement.categoryId, aAchievement.dateCompleted, aAchievement.desc, aAchievement.icon, aAchievement.id, aAchievement.points, aAchievement.reward, aAchievement.title))
            Next

            For Each cCategory As Schema.rootCategories_category In caPage.achievements.First.rootCategories.First.category
                cCategories.Add(New CategoryInfo(cCategory.id, cCategory.name, (From c In cCategory.category Select New SubcategoryInfo(c.name)).ToCollection))
            Next

            For Each cCategory As CategoryInfo In cCategories
                Dim scCategory As Schema.summary_category = caPage.achievements.First.summary.First.category(cCategories.IndexOf(cCategory))
                cCategory.Earned = scCategory.c.First.earned
                cCategory.EarnedPoints = scCategory.c.First.earnedPoints
                cCategory.Total = scCategory.c.First.total
                cCategory.TotalPoints = scCategory.c.First.totalPoints
            Next
        End Sub

        ''' <summary>
        ''' A character's achievements for a single category
        ''' </summary>
        ''' <param name="cCategory"></param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Function CategoryAchievements(ByVal cCategory As CategoryInfo) As CharacterAchievementsCategory
            If cCategory Is Nothing Then
                Return Nothing
            End If
            Return New CharacterAchievementsCategory(Realm, Name, cCategory.CategoryID)
        End Function

    End Class

End Namespace
